package prototype.deepcopy;

import java.io.*;

public class DeepProtoType implements Serializable, Cloneable{

    public String name; //String 属性
    public DeepCloneableTarget deepCloneableTarget;// 引用类型

    public DeepProtoType() {
        super();
    }

    // 深拷贝 - 方式 1 使用clone 方法
    // 这种方式的缺点就是每次有新增的引用属性都需要定制的进行更改代码
    @Override
    protected Object clone() throws CloneNotSupportedException {

        Object deep = null;
        //这里完成对基本数据类型(属性)和String的克隆
        deep = super.clone();
        //对引用类型的属性，进行单独处理
        DeepProtoType deepProtoType = (DeepProtoType)deep;
        deepProtoType.deepCloneableTarget  = (DeepCloneableTarget)deepCloneableTarget.clone();

        // TODO Auto-generated method stub
        return deepProtoType;
    }

    //深拷贝 - 方式2 通过对象的序列化实现 (推荐)！！！！
    public Object deepClone() {

        //创建流对象
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;

        try {

            //序列化(输出去)
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); //当前这个对象以对象流的方式输出

            //反序列化（读进来）
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepProtoType copyObj = (DeepProtoType)ois.readObject();

            return copyObj;

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                // TODO: handle exception
                System.out.println(e2.getMessage());
            }
        }
    }

    public void testCopy() throws IOException, ClassNotFoundException {
        // 字节流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        // 将 bos 设置为 oos 的容器（结果转换后要存放的地方）
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        // 将自身对象转为对象流存到字节流 bos 中去
        oos.writeObject(this);
        // 将字节流 bos 中的数据存到 bis 流中待读出
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        // 为了读出对象，需要用 ois 来读
        ObjectInputStream ois = new ObjectInputStream(bis);
        // 具体读取对象（此时拷贝已经完成）
        DeepProtoType result = (DeepProtoType) ois.readObject();
    }

}
